home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 November: Tool Chest / Dev.CD Nov 96 TC / Dev.CD Nov 96 TC.toast / Sample Code / Snippets / Files / SettingUpStdFile / Source / SettingUpStdFile.c
Encoding:
C/C++ Source or Header  |  1996-09-17  |  7.0 KB  |  251 lines  |  [TEXT/CWIE]

  1. /*
  2.  * Setting Up StandardFile
  3.  *  
  4.  *  This snippet demonstrates how to make Standard File
  5.  *  select an initial file under both System 6 and System 7.
  6.  *  (In this example, the System file will be selected.)
  7.  *
  8.  *  "An exhilirating snippet"
  9.  *             - Nitin Ganatra
  10.  *
  11.  *  Greg Robbins   August 1993
  12.  *
  13.  * Changes:
  14.  * =======
  15.  * • sfScript is reset in the System 7 DialogHook (below) to work  
  16.  *   around a gotcha in Standard File that's incorrectly documented in  
  17.  *   a New Inside Macintosh: Files sample.  See the DialogHook() function 
  18.  *   for details.
  19.  *
  20.  *
  21.  * • Compatible with the Universal Interfaces.
  22.  *
  23.  *  Nitin Ganatra, 2/94
  24.  *
  25.  */
  26.  
  27. #include <QuickDraw.h>
  28. #include <StandardFile.h>
  29. #include <Fonts.h>
  30. #include <Menus.h>
  31. #include <Dialogs.h>
  32. #include <Events.h>
  33. #include <GestaltEqu.h>
  34. #include <TextEdit.h>
  35. #include <Errors.h>
  36. #include <OSEvents.h>
  37. #include <Folders.h>
  38. #include <Memory.h>
  39. #include <Script.h>
  40. #include <LowMem.h>
  41.  
  42. // prototypes
  43. pascal short DialogHook(short, DialogPtr , void *);
  44. pascal short OldDlgHook(short, DialogPtr);
  45. OSErr GetSystemFileSpec(FSSpecPtr);
  46.  
  47. // global struct for System 7 Std File dialog hook
  48. typedef struct {
  49.     StandardFileReply *theSFR;
  50.     FSSpec *itemSpec;
  51. } HookRecord, *HookRecordPtr;
  52.  
  53. // globals for System 6 Std File stuff
  54. StringPtr    gSelectFileName;
  55. short        gSelectFileCounter;
  56.  
  57.  
  58.  
  59.  
  60. void main(void)
  61. {
  62.     Point dialogPt;
  63.     SFTypeList mySFTypeList;
  64.     StandardFileReply mySFR;
  65.     SFReply oldSFR;
  66.     long procID;
  67.     FSSpec systemSpec;
  68.     HookRecord hookRec;
  69.     Boolean hasNewStdFileCallsFlag;
  70.     long gestResponse;
  71.     
  72.     OSErr retCode;
  73.     DlgHookYDUPP    myDlgHookUPP;
  74.  
  75.  
  76.     // initialize the toolbox
  77.     InitGraf(&qd.thePort); InitFonts(); InitWindows(); InitMenus();
  78.     TEInit(); InitDialogs(nil); InitCursor(); FlushEvents(everyEvent,0);
  79.  
  80.     // determine if the System 7 std file calls are available
  81.     retCode = Gestalt(gestaltStandardFileAttr, &gestResponse);
  82.     if (retCode == noErr && ((gestResponse >> gestaltStandardFile58) & 1) != 0)
  83.         hasNewStdFileCallsFlag = true;
  84.     else
  85.         hasNewStdFileCallsFlag = false;
  86.  
  87.     SetPt(&dialogPt, -1, -1);
  88.         
  89.     // get the FSSpec of the system file
  90.     retCode = GetSystemFileSpec(&systemSpec);
  91.     if (retCode != noErr) DebugStr((StringPtr)"\p GetSystemFileSpec failed");
  92.     
  93.     if (hasNewStdFileCallsFlag) {
  94.     
  95.         // System 7 method
  96.         
  97.         // point my hook data record at the reply record and at
  98.         // the file spec for the system file
  99.         
  100.         hookRec.itemSpec = &systemSpec;
  101.         hookRec.theSFR = &mySFR;
  102.  
  103.  
  104.         // Set up the universal proc pointer to your hook routine with this 
  105.         // macro defined in StandardFile.h.  **NOTE** This is different
  106.         // from the macro used for System 6 dialog hooks, and you should get
  107.         // a compiler error if you try to use the wrong UPP with the wrong call.
  108.         myDlgHookUPP = NewDlgHookYDProc(DialogHook);
  109.         
  110.         // call Std File
  111.         CustomGetFile(nil, -1, mySFTypeList, &mySFR, 0, dialogPt, myDlgHookUPP,
  112.             nil, nil, nil, &hookRec);
  113.             
  114.         // Dispose of the routine descriptor, since they do allocate memory..
  115.         DisposeRoutineDescriptor(myDlgHookUPP);
  116.  
  117.  
  118.     }
  119.     
  120.     else {
  121.         // System 6 method
  122.     
  123.         // stuff low memory to display the proper initial directory; 
  124.         // see Inside Mac:Files 3-31
  125.         
  126.         DlgHookUPP    myOldDlgHookUPP;
  127.         
  128.         // Throw out your SysEqu.h file and start using the low memory 
  129.         // accessor functions provided in LowMem.h.
  130.         LMSetSFSaveDisk(-systemSpec.vRefNum);
  131.         LMSetCurDirStore(systemSpec.parID);
  132.  
  133.         // set up the string for the system file name
  134.         gSelectFileName = systemSpec.name;
  135.  
  136.         // Set up the universal proc pointer to your hook routine with this 
  137.         // macro defined in StandardFile.h.  **NOTE** This is different
  138.         // from the macro used for System 7 dialog hooks, and you should get
  139.         // a compiler error if you try to use the wrong UPP with the wrong call.
  140.         myOldDlgHookUPP = NewDlgHookProc(OldDlgHook);
  141.         
  142.         // call Std File
  143.         SFGetFile(dialogPt, nil, nil, -1, mySFTypeList, myOldDlgHookUPP, &oldSFR);
  144.  
  145.         // Dispose of the routine descriptor, since they do allocate memory..
  146.         DisposeRoutineDescriptor(myOldDlgHookUPP);
  147.         
  148.         // store the result in a new reply record
  149.         mySFR.sfGood = oldSFR.good;
  150.         if (oldSFR.good) {
  151.         
  152.             // convert the WDRefNum and copy the name string
  153.             retCode = GetWDInfo(oldSFR.vRefNum, 
  154.                 &mySFR.sfFile.vRefNum, &mySFR.sfFile.parID, &procID);
  155.             BlockMove(oldSFR.fName, mySFR.sfFile.name, 1 + oldSFR.fName[0]);
  156.         }
  157.     }
  158. }
  159.  
  160. // this dialog hook for System 7 std file selects
  161. // the file specified by the hookRecord supplied as userData
  162.  
  163. pascal short DialogHook(short item, DialogPtr theDialog, 
  164.     void *userData)
  165. {
  166.     HookRecordPtr hookRecPtr;
  167.     
  168.     hookRecPtr = (HookRecordPtr) userData;
  169.     
  170.     // hookRecPtr->itemSpec points to the FSSpec of the item to be selected
  171.     // hookRecPtr->theSFR points to the standard file reply record
  172.  
  173.     // make sure we're dealing with the proper dialog
  174.     if (GetWRefCon(theDialog) == sfMainDialogRefCon) {
  175.     
  176.         // just when opening the dialog...
  177.         if (item == sfHookFirstCall) {
  178.     
  179.             // make the reply record hold the spec of the specified item
  180.             hookRecPtr->theSFR->sfFile = *hookRecPtr->itemSpec;
  181.             
  182.             // There’s a gotcha in Standard File when using sfHookChangeSelection. 
  183.             // Even though New Inside Macintosh: Files has a sample that doesn't set
  184.             // the sfScript field, it should be set, or the last object in the
  185.             // selected directory  will always be selected.
  186.             hookRecPtr->theSFR->sfScript = smSystemScript;
  187.  
  188.             // tell std file to change the selection to that item
  189.             item = sfHookChangeSelection;
  190.         }
  191.     }            
  192.         
  193.     return item;
  194. }
  195.  
  196.  
  197. // this std file dialog hook for System 6 selects the file
  198. // name in the global gSelectFileName
  199.  
  200. pascal short OldDlgHook(short item, DialogPtr theDialog)
  201. {
  202. #pragma unused (theDialog)
  203.     
  204.     // the idea here is to post keydown events, one per
  205.     // null hook-event, until the entire file name
  206.     // has been "typed" in (remember that the event queue
  207.     // is shorter than the maximum file name so we only post
  208.     // one key per null event)
  209.  
  210.     // reset the character counter initially
  211.     
  212.     if (item == sfHookFirstCall)
  213.         gSelectFileCounter = 0;
  214.         
  215.     // post one keyDown per null event until the string is exhausted
  216.     // This may not be a good idea for international software since 
  217.     // different input methods may be used.
  218.     // Instead, you may want to check the System version and temporarily 
  219.     // set the KeyScript to zero before doing these PostEvents.  
  220.     // Afterwards, set KeyScript back to its original mode.
  221.     else if (item == sfHookNullEvent) {
  222.         if (gSelectFileCounter < *gSelectFileName) {
  223.             gSelectFileCounter++;
  224.             PostEvent(keyDown, *(gSelectFileName+gSelectFileCounter));
  225.         }
  226.     }
  227.  
  228.     return item;
  229. }
  230.  
  231.  
  232. OSErr GetSystemFileSpec(FSSpecPtr systemSpec)
  233. {
  234.     // the System folder location is returned by FindFolder (or under
  235.     // System 6 by the compiler's FindFolder glue)
  236.     //
  237.     // the System file name is available in low-memory
  238.     
  239.     OSErr         retCode;
  240.     StringPtr    systemName;
  241.     
  242.     systemName = LMGetSysResName();        // Get the name of the System resource file
  243.  
  244.     retCode = FindFolder(kOnSystemDisk, kSystemFolderType, kCreateFolder,
  245.         &systemSpec->vRefNum, &systemSpec->parID);
  246.     if (retCode == noErr)
  247.         BlockMove((Ptr)systemName, systemSpec->name, systemName[0] + 1);
  248.     
  249.     return retCode;
  250. }
  251.